package com.nuoniu.sibanyun.service.finance.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.dto.AccountingLedgerDto;
import com.nuoniu.sibanyun.entity.erp.ErpAccount;
import com.nuoniu.sibanyun.entity.erp.ErpAccounting;
import com.nuoniu.sibanyun.entity.erp.ErpPeriod;
import com.nuoniu.sibanyun.entity.finance.VAccountingLedger;
import com.nuoniu.sibanyun.entity.finance.VAccountingSearchProgramme;
import com.nuoniu.sibanyun.entity.finance.VAccountingVoucherDetail;
import com.nuoniu.sibanyun.entity.finance.VAssetsLiabilitiesFormula;
import com.nuoniu.sibanyun.entity.vo.VAccountingLedgerVo;
import com.nuoniu.sibanyun.mapper.erp.ErpAccountingMapper;
import com.nuoniu.sibanyun.mapper.finance.VAccountingLedgerMapper;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpPeriodService;
import com.nuoniu.sibanyun.service.finance.IVAccountingAuxiliaryLedgerService;
import com.nuoniu.sibanyun.service.finance.IVAccountingLedgerService;
import com.nuoniu.sibanyun.service.finance.IVAccountingVoucherDetailService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 科目总账 服务实现类
 * </p>
 *
 * @author 小啊刚
 * @since 2021-04-25
 */
@Service
public class VAccountingLedgerServiceImpl extends ServiceImpl<VAccountingLedgerMapper, VAccountingLedger> implements IVAccountingLedgerService {

    @Autowired
    private IVAccountingAuxiliaryLedgerService accountingAuxiliaryLedgerService;
    @Autowired
    private ErpAccountingMapper accountingMapper;
    @Autowired
    private IErpAccountService accountService;
    @Autowired
    private IErpPeriodService periodService;
    @Autowired
    private IVAccountingVoucherDetailService voucherDetailService;

    @Override
    public void saveAccounting(List<VAccountingVoucherDetail> voucherDetails) {
        UserInfo userInfo = UserThreadLocal.get();
        ErpAccount account = accountService.getLastErpAccount();
        for (VAccountingVoucherDetail voucherDetail : voucherDetails) {
            voucherDetail.setCompanyId(userInfo.getCompanyId());
            voucherDetail.setAccountId(accountService.getCurrentAccountId());
            ErpPeriod period = periodService.getByPeriod(voucherDetail.getAccountYear(), voucherDetail.getAccountPeriod());
            if (period != null) {
                if (period.getFiTerminalState() != null && period.getFiTerminalState().equals(1)) {
                    throw new NuoNiuException("当前期间已财务结账");
                }
            }


            ErpAccounting accounting = accountingMapper.selectById(voucherDetail.getAccountingId());
            if (accounting != null) {
                /** 科目总账计算*/
                VAccountingLedger accountingLedger = baseMapper.getById(voucherDetail.getAccountingId(), voucherDetail.getAccountYear(), voucherDetail.getAccountPeriod());
                if (accountingLedger == null) { //计算科目总账
                    accountingLedger = new VAccountingLedger();
                    BeanUtils.copyProperties(voucherDetail, accountingLedger);
                    accountingLedger.setAccountingParentId(accounting.getParentId());
                    accountingLedger.setAccountingDepth(accounting.getDepth());
                    accountingLedger.setAccountingName(accounting.getName());
                    accountingLedger.setIsEndNode(accounting.getIsEndNode() ? 1 : 0);
                } else { //累加科目总账
                    accountingLedger.setDebitAmount(accountingLedger.getDebitAmount().add(voucherDetail.getDebitAmount()));
                    accountingLedger.setCreditAmount(accountingLedger.getCreditAmount().add(voucherDetail.getCreditAmount()));
                }

                //获取上一期间科目
                Integer accountPeriod = account.getEnableDuration();
                VAccountingLedger upAccountingLedger = baseMapper.getUpLedger(voucherDetail.getAccountingId(), voucherDetail.getAccountYear(), accountPeriod.equals(period.getCurrentPeriod()) ? accountPeriod + 1 : period.getCurrentPeriod());
                //科目期初余额设置
                if (upAccountingLedger == null) {
                    accountingLedger.setBeginAmount(new BigDecimal(0.0));
                    accountingLedger.setBeginAmountDirection(3);
                    accountingLedger.setCurrencyBeginAmount(new BigDecimal(0.0));
                    accountingLedger.setQuantityBegin(new BigDecimal(0.0));
                } else {
                    if (!accountPeriod.equals(period.getCurrentPeriod())) {
                        accountingLedger.setBeginAmount(upAccountingLedger.getEndAmount());
                        accountingLedger.setBeginAmountDirection(upAccountingLedger.getEndAmountDirection());
                        accountingLedger.setCurrencyBeginAmount(upAccountingLedger.getCurrencyEndAmount());
                        accountingLedger.setQuantityBegin(upAccountingLedger.getQuantityEnd());
                    } else {
                        accountingLedger.setBeginAmount(upAccountingLedger.getBeginAmount());
                        accountingLedger.setBeginAmountDirection(upAccountingLedger.getBeginAmountDirection());
                        accountingLedger.setCurrencyBeginAmount(upAccountingLedger.getCurrencyEndAmount());
                        accountingLedger.setQuantityBegin(upAccountingLedger.getQuantityEnd());
                    }
                }

                //计算期末
                countEnd(accountingLedger);
                //计算上级科目
                if (accounting.getDepth() > 1) {
                    countUpAccounting(accountingLedger, accounting, voucherDetail, 1);
                }

                //保存
                saveOrUpdate(accountingLedger);

                /** 依次计算后面期间科目总账*/
                countNextAccounting(accountingLedger, accounting, voucherDetail);

                /** 辅助总账计算*/
                if (voucherDetail.getCustomerId() != null || voucherDetail.getEmployeeId() != null || voucherDetail.getVendorId() != null || voucherDetail.getOfficeId() != null || voucherDetail.getProjectId() != null) {
                    accountingAuxiliaryLedgerService.bookAccounting(voucherDetail, accounting, accountPeriod);
                }
//                if (voucherDetail.getCrmId() != null || voucherDetail.getUserId() != null || voucherDetail.getVendorId() != null || voucherDetail.getOfficeId() != null || voucherDetail.getProjectId() != null) {
//                    accountingAuxiliaryLedgerService.bookAccounting(voucherDetail, accounting, accountPeriod);
//                }
            }
        }
    }

    /**
     * 计算上级科目
     *
     * @author 小啊刚
     * @date 2021-04-30
     */
    public void countUpAccounting(VAccountingLedger accountingLedger, ErpAccounting accounting, VAccountingVoucherDetail voucherDetail, Integer type) {
        if (accounting.getParentIds() == null) {
            return;
        }

        List<ErpAccounting> accountingParents = accountingMapper.getByParentIds(accounting.getParentIds());
        for (ErpAccounting erpAccounting : accountingParents) {
            VAccountingLedger accountingLedgerParent = baseMapper.getById(erpAccounting.getId().intValue(), voucherDetail.getAccountYear(), accountingLedger.getAccountPeriod());
            if (accountingLedgerParent == null) {
                accountingLedgerParent = new VAccountingLedger();
                BeanUtils.copyProperties(accountingLedger, accountingLedgerParent);
                accountingLedgerParent.setId(null);
                accountingLedgerParent.setAccountingParentId(erpAccounting.getParentId());
                accountingLedgerParent.setAccountingDepth(erpAccounting.getDepth());
                accountingLedgerParent.setAccountingName(erpAccounting.getName());
                accountingLedgerParent.setAccountingCode(erpAccounting.getCode());
                accountingLedgerParent.setAccountingId(erpAccounting.getId().intValue());
                accountingLedgerParent.setIsEndNode(0);
            } else {
                //计算借贷金额
                if (type.equals(1)) {
                    if (voucherDetail.getDebitAmount() != null) {
                        accountingLedgerParent.setDebitAmount(accountingLedgerParent.getDebitAmount().add(voucherDetail.getDebitAmount()));
                    }

                    if (voucherDetail.getCreditAmount() != null) {
                        accountingLedgerParent.setCreditAmount(accountingLedgerParent.getCreditAmount().add(voucherDetail.getCreditAmount()));
                    }
                }

                //计算期初金额
                if (accountingLedger.getBeginAmountDirection().equals(accountingLedgerParent.getBeginAmountDirection())) {
                    accountingLedgerParent.setBeginAmount(accountingLedgerParent.getBeginAmount().add(accountingLedger.getBeginAmount()));
                } else {
                    accountingLedgerParent.setBeginAmount(accountingLedgerParent.getBeginAmount().subtract(accountingLedger.getBeginAmount()));
                    //设置期初方向
                    if (accountingLedgerParent.getBeginAmount().compareTo(BigDecimal.ZERO) == -1) {
                        accountingLedgerParent.setBeginAmountDirection(1);
                        accountingLedgerParent.setBeginAmount(accountingLedgerParent.getBeginAmount().abs());
                    } else if (accountingLedgerParent.getBeginAmount().compareTo(BigDecimal.ZERO) == 0) {
                        accountingLedgerParent.setBeginAmountDirection(3);
                    }
                }
            }

            //计算期末
            countEnd(accountingLedgerParent);
            //保存
            saveOrUpdate(accountingLedgerParent);
        }
    }

    /**
     * 计算后面期间科目总账
     *
     * @author 小啊刚
     * @date 2021-04-30
     */
    public void countNextAccounting(VAccountingLedger accountingLedger, ErpAccounting accounting, VAccountingVoucherDetail voucherDetail) {
        List<VAccountingLedger> accountingLedgers = new ArrayList<>();
        Map<Integer, VAccountingLedger> ledgerMap = new HashMap<>();
        ledgerMap.put(accountingLedger.getAccountPeriod(), accountingLedger);
        for (int i = accountingLedger.getAccountPeriod() + 1; i <= 12; i++) {
            VAccountingLedger ledger = baseMapper.getById(accountingLedger.getAccountingId(), accountingLedger.getAccountYear(), i);
            if (ledger == null) {
                ledger = new VAccountingLedger();
                BeanUtils.copyProperties(accountingLedger, ledger);
                ledger.setEndAmountDirection(accounting.getDcDirection());
                ledger.setBeginAmountDirection(accounting.getDcDirection());
                ledger.setId(null);
                ledger.setDebitAmount(new BigDecimal(0.0));
                ledger.setCreditAmount(new BigDecimal(0.0));
                ledger.setAccountPeriod(i);
                ledger.setBeginAmount(accountingLedger.getEndAmount());
            } else {
                ledger.setEndAmountDirection(accounting.getDcDirection());
                ledger.setBeginAmountDirection(accounting.getDcDirection());
                ledger.setBeginAmount(ledgerMap.get(i - 1).getEndAmount());
                countEnd(ledger);
            }

            ledgerMap.put(i, ledger);
            accountingLedgers.add(ledger);
            //计算上级
            countUpAccounting(ledger, accounting, voucherDetail, 2);
        }

        saveOrUpdateBatch(accountingLedgers);
    }

    /**
     * 计算期末
     *
     * @author 小啊刚
     * @date 2021-05-10
     */
    public void countEnd(VAccountingLedger accountingLedger) {
        ErpAccounting accounting = accountingMapper.selectById(accountingLedger.getAccountingId());
        accountingLedger.setEndAmountDirection(accounting.getDcDirection());
        if (accounting.getDcDirection().equals(1)) {
            if (accountingLedger.getBeginAmountDirection() != null && accountingLedger.getBeginAmountDirection().equals(1)) {
                accountingLedger.setEndAmount(accountingLedger.getBeginAmount().add(accountingLedger.getDebitAmount()).subtract(accountingLedger.getCreditAmount()));
            } else {
                accountingLedger.setEndAmount((accountingLedger.getBeginAmount().multiply(new BigDecimal(-1))).add(accountingLedger.getDebitAmount()).subtract(accountingLedger.getCreditAmount()));
            }
        } else {
            if (accountingLedger.getBeginAmountDirection() != null && accountingLedger.getBeginAmountDirection().equals(2)) {
                accountingLedger.setEndAmount(accountingLedger.getBeginAmount().add(accountingLedger.getCreditAmount()).subtract(accountingLedger.getDebitAmount()));
            } else {
                accountingLedger.setEndAmount((accountingLedger.getBeginAmount().multiply(new BigDecimal(-1))).add(accountingLedger.getCreditAmount()).subtract(accountingLedger.getDebitAmount()));
            }
        }

    }

    @Override
    public Map<String, Object> saveLedger(List<VAccountingLedgerVo> accountingLedgerVo) {
        UserInfo userInfo = UserThreadLocal.get();
        ErpAccount account = accountService.getLastErpAccount();
        List<VAccountingLedger> ledgerList = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        List<String> resultData = new ArrayList<>();

        Integer aCount = baseMapper.checkAccounting(userInfo.getCompanyId(), account.getAccountYear());
        if (aCount > 0) {
            throw new NuoNiuException("已记账,不能设置期初余额");
        }

        accountingLedgerVo.forEach(a -> {
            if (a.getBeginAmount() != null) {
                VAccountingLedger ledger = new VAccountingLedger();
                BeanUtils.copyProperties(a, ledger);
                ledger.setCompanyId(userInfo.getCompanyId());
                ledger.setAccountId(account.getId().intValue());
                ledger.setAccountYear(account.getAccountYear());
                if (ledger.getAccountPeriod() == null) {
                    ledger.setAccountPeriod(account.getEnableDuration());
                }
                ledgerList.add(ledger);
            }
        });

        saveOrUpdateBatch(ledgerList);
        resultMap.put("result", resultData);
        resultMap.put("sCount", accountingLedgerVo.size() - resultData.size());
        resultMap.put("fCount", resultData.size());
        return resultMap;
    }

    @Override
    public Integer getByAccountingId(Long id) {
        return baseMapper.getByAccountingId(id);
    }

    @Override
    public List<VAccountingLedgerVo> getList(Integer accountingTypeId, String name, String code) {
        UserInfo userInfo = UserThreadLocal.get();
        ErpAccount account = accountService.getLastErpAccount();
        return baseMapper.getList(userInfo.getCompanyId(), account.getAccountYear(), account.getEnableDuration(), accountingTypeId, name, code);
    }

    @Override
    public Page<VAccountingLedger> pageEndAccountingList(Page page, VAccountingSearchProgramme searchProgramme) {
        UserInfo userInfo = UserThreadLocal.get();
        page.setSize(-1);
        searchProgramme.setCompanyId(userInfo.getCompanyId());
        searchProgramme.setAccountYear(accountService.getLastErpAccount().getAccountYear());
        searchProgramme.setBeginDate(searchProgramme.getBeginDate().split("-")[1]);
        searchProgramme.setEndDate(searchProgramme.getEndDate().split("-")[1]);
        Page<VAccountingLedger> ledgerPage = baseMapper.pageEndAccountingList(page, searchProgramme);
        List<VAccountingLedger> ledgerList = ledgerPage.getRecords();
        for (VAccountingLedger ledger : ledgerList) {
            ErpAccounting accounting = accountingMapper.selectById(ledger.getAccountingId());
            if (accounting != null) {
                ledger.setEndAmountDirection(accounting.getDcDirection());
            }
        }
        return ledgerPage;
    }

    @Override
    public Page<AccountingLedgerDto> getGeneralLedgerList(Page page, VAccountingSearchProgramme searchProgramme, Boolean isShowDetail, Boolean isDayBook) {
        List<AccountingLedgerDto> ledgerDtoList = new ArrayList<>(); //数据组装
        Map<String, VAccountingLedger> dtoMap = new HashMap<>(); //年度累计
        VAccountingLedger upLedger = null; //上个期间数据
        UserInfo userInfo = UserThreadLocal.get();
        ErpAccount account = accountService.getLastErpAccount();
        Integer period = getAccountPeriod(account.getAccountYear(), userInfo.getCompanyId());
        searchProgramme.setCompanyId(userInfo.getCompanyId());
        searchProgramme.setAccountYear(account.getAccountYear());
        searchProgramme.setBeginDate(searchProgramme.getBeginDate().split("-")[1]);
        searchProgramme.setEndDate(searchProgramme.getEndDate().split("-")[1]);
        ErpAccounting accounting = accountingMapper.selectById(searchProgramme.getAccountingId());

        //获取已记账科目数据
        Page<VAccountingLedger> ledgerPage = baseMapper.getGeneralLedgerList(page, searchProgramme);

        for (VAccountingLedger ledger : ledgerPage.getRecords()) {
            if (StringUtils.isNotBlank(searchProgramme.getBeginCode()) && (upLedger == null || !upLedger.getAccountingCode().equals(ledger.getAccountingCode()))) { //设置期初
                AccountingLedgerDto dto = new AccountingLedgerDto();
                if (ledger.getAccountPeriod().equals(period) && ledger.getAccountPeriod() > 1) {
                    dto.setPeriodDate(ledger.getAccountYear() + "年1-" + period + "月");
                } else {
                    dto.setPeriodDate(ledger.getPeriodDate());
                }
                dto.setEndAmount(ledger.getBeginAmount());
                dto.setEndAmountDirection(ledger.getBeginAmountDirection());
                dto.setTitle("期初余额");
                ledgerDtoList.add(dto);
            }

            if (isShowDetail != null && isShowDetail && (upLedger == null || !upLedger.getAccountPeriod().equals(ledger.getAccountPeriod()))) { //获取总账明细
                searchProgramme.setAccountPeriod(ledger.getAccountPeriod());
                List<AccountingLedgerDto> ledgerDetailList = voucherDetailService.getLedgerDetailList(searchProgramme);
                BigDecimal dayCreditAmount = new BigDecimal(0.0);
                BigDecimal dayDebitAmount = new BigDecimal(0.0);
                VAccountingLedger dLedger = new VAccountingLedger();
                dLedger.setEndAmount(ledger.getBeginAmount());
                dLedger.setBeginAmount(ledger.getBeginAmount());
                dLedger.setBeginAmountDirection(ledger.getBeginAmountDirection());
                if (accounting.getDcDirection().equals(1)) {
                    if (ledger.getBeginAmountDirection().equals(2)) {
                        dLedger.setBeginAmount(ledger.getBeginAmount().multiply(new BigDecimal(-1)));
                    }
                } else {
                    if (ledger.getBeginAmountDirection().equals(1)) {
                        dLedger.setBeginAmount(ledger.getBeginAmount().multiply(new BigDecimal(-1)));
                    }
                }

                for (Integer i = 0; i < ledgerDetailList.size(); i++) {
                    AccountingLedgerDto ledgerDto = ledgerDetailList.get(i);
                    //设置明细账期末余额
                    BigDecimal creditAmount = ledgerDto.getCreditAmount() != null ? ledgerDto.getCreditAmount() : new BigDecimal(0.0);
                    BigDecimal debitAmount = ledgerDto.getDebitAmount() != null ? ledgerDto.getDebitAmount() : new BigDecimal(0.0);
                    if (accounting.getDcDirection().equals(1)) {
                        ledgerDto.setEndAmountDirection(1);
                        dLedger.setEndAmount(dLedger.getEndAmount().add(debitAmount).subtract(creditAmount));
                        ledgerDto.setEndAmount(dLedger.getEndAmount());
                    } else {
                        dLedger.setEndAmount(dLedger.getEndAmount().add(creditAmount).subtract(debitAmount));
                        ledgerDto.setEndAmountDirection(2);
                        ledgerDto.setEndAmount(dLedger.getEndAmount());
                    }
                    ledgerDtoList.add(ledgerDto);

                    if (isDayBook != null && isDayBook) { //日记账
                        dayCreditAmount = dayCreditAmount.add(creditAmount);
                        dayDebitAmount = dayDebitAmount.add(debitAmount);

                        if (ledgerDetailList.size() == 1 || ledgerDetailList.size() == i + 1 || (!ledgerDto.getPeriodDate().equals(ledgerDetailList.get(i + 1).getPeriodDate()))) {
                            AccountingLedgerDto dayLedger = new AccountingLedgerDto();
                            BeanUtils.copyProperties(ledgerDto, dayLedger);
                            dayLedger.setDebitAmount(dayDebitAmount);
                            dayLedger.setCreditAmount(dayCreditAmount);
                            dayLedger.setTitle("本日合计");
                            dayLedger.setCode("");
                            dayCreditAmount = new BigDecimal(0.0);
                            dayDebitAmount = new BigDecimal(0.0);
                            ledgerDtoList.add(dayLedger);
                        }
                    }
                }
            }

            if (searchProgramme.getIsNoBookkeeping() != null && searchProgramme.getIsNoBookkeeping().equals(1)) { //计算未记账
                ledger.setCreditAmount(ledger.getCreditAmount().add(ledger.getNoCreditAmount()));
                ledger.setDebitAmount(ledger.getDebitAmount().add(ledger.getNoDebitAmount()));
                countEnd(ledger);
            }

            AccountingLedgerDto mDto = new AccountingLedgerDto();
            BeanUtils.copyProperties(ledger, mDto);
            if (ledger.getAccountPeriod().equals(period) && ledger.getAccountPeriod() > 1) {
                mDto.setPeriodDate(ledger.getAccountYear() + "年1-" + period + "月");
            } else {
                mDto.setPeriodDate(ledger.getPeriodDate());
            }

            mDto.setTitle("本月合计");
            ledgerDtoList.add(mDto);

            if (dtoMap == null || dtoMap.get(ledger.getAccountingCode()) == null) {
                dtoMap.put(ledger.getAccountingCode(), ledger);
            } else {
                VAccountingLedger accountingLedger = dtoMap.get(ledger.getAccountingCode());
                accountingLedger.setDebitAmount(accountingLedger.getDebitAmount().add(ledger.getDebitAmount()));
                accountingLedger.setCreditAmount(accountingLedger.getCreditAmount().add(ledger.getCreditAmount()));
                dtoMap.put(ledger.getAccountingCode(), accountingLedger);
            }

            AccountingLedgerDto yDto = new AccountingLedgerDto();
            BeanUtils.copyProperties(ledger, yDto);
            if (ledger.getAccountPeriod().equals(period) && ledger.getAccountPeriod() > 1) {
                yDto.setPeriodDate(ledger.getAccountYear() + "年1-" + period + "月");
            } else {
                yDto.setPeriodDate(ledger.getPeriodDate());
            }

            yDto.setCreditAmount(dtoMap.get(ledger.getAccountingCode()).getCreditAmount());
            yDto.setDebitAmount(dtoMap.get(ledger.getAccountingCode()).getDebitAmount());
            yDto.setTitle("本年累计");
            ledgerDtoList.add(yDto);
            upLedger = ledger;
        }

        Page<AccountingLedgerDto> ledgerDtoPage = new Page<>();
        BeanUtils.copyProperties(ledgerPage, ledgerDtoPage);
        ledgerDtoPage.setRecords(ledgerDtoList);
        return ledgerDtoPage;
    }

    @Override
    public Page<AccountingLedgerDto> getGeneralDetailLedgerList(Page page, VAccountingSearchProgramme searchProgramme) {
        return null;
    }

    @Override
    public List<VAccountingLedger> getList(Integer companyId, Integer accountYear) {
        return baseMapper.getBeginList(companyId, accountYear);
    }

    @Override
    public VAccountingLedger getById(Integer accountingId, Integer accountYear, int period) {
        return baseMapper.getById(accountingId, accountYear, period);
    }

    @Override
    public List<VAccountingLedger> getAccountingLedger(String code, Integer accountPeriod) {
        UserInfo userInfo = UserThreadLocal.get();
        ErpAccount account = accountService.getLastErpAccount();
        QueryWrapper wrapper = new QueryWrapper();

        wrapper.eq("company_id", userInfo.getCompanyId());
        wrapper.eq("account_year", account.getAccountYear());
        if (accountPeriod != null) {
            wrapper.eq("account_period", accountPeriod);
        }

        return list(wrapper);
    }

    @Override
    public BigDecimal getFinalBalance(Integer accountingId, Integer accountYear, Integer accountPeriod) {
        UserInfo userInfo = UserThreadLocal.get();
        BigDecimal balance = new BigDecimal(0.0);
        ErpAccounting accounting = accountingMapper.selectById(accountingId);
        Map param = new HashMap();
        param.put("companyId", userInfo.getCompanyId());
        param.put("accountingCode", accounting.getCode());
        param.put("accountYear", accountYear);
        if (accountPeriod > 0) {
            param.put("accountPeriod", accountPeriod);
        }

        List<VAccountingLedger> finalBalance = baseMapper.getFinaBalance(param);
        for (VAccountingLedger ledger : finalBalance) {
            if (ledger.getEndAmountDirection().equals(1)) {
                balance.add(ledger.getEndAmount().multiply(new BigDecimal(-1)));
            } else {
                balance.add(ledger.getEndAmount());
            }
        }
        return balance;
    }

    @Override
    public VAccountingLedger getYearBalance(Integer accountingId, Integer accountYear, Integer accessRule) {
        UserInfo userInfo = UserThreadLocal.get();
        BigDecimal balance = new BigDecimal(0.0);
        Map param = new HashMap();
        param.put("companyId", userInfo.getCompanyId());
        param.put("accountingId", accountingId);
        param.put("accountYear", accountYear);

        List<VAccountingLedger> yearBalance = baseMapper.getYearBalance(param);
        for (VAccountingLedger ledger : yearBalance) {
            if (accessRule.equals(2) && ledger.getBeginAmountDirection().equals(1)) {
                return ledger;
            }

            if (accessRule.equals(3) && ledger.getBeginAmountDirection().equals(2)) {
                return ledger;
            }

            if (ledger.getBeginAmountDirection().equals(1)) {
                balance.add(ledger.getBeginAmount()).multiply(new BigDecimal(-1));
            } else {
                balance.add(ledger.getBeginAmount());
            }
        }

        VAccountingLedger ledger = new VAccountingLedger();
        ledger.setBeginAmount(balance);
        if (balance.compareTo(BigDecimal.ZERO) == 1) {
            ledger.setBeginAmountDirection(2);
        } else {
            ledger.setBeginAmountDirection(1);
        }
        return ledger;
    }

    /**
     * 计算公式的值
     *
     * @author 小啊刚
     * @date 2021-06-15
     */
    public void countFormula(VAssetsLiabilitiesFormula a, Integer accountYear) {
        for (int i = 1; i < 13; i++) {
            BigDecimal balance = null;
            VAccountingLedger ledger = this.getById(a.getAccountingId(), accountYear, i);
            if (ledger != null) {
                balance = ledger.getEndAmount();
            }

            switch (i) {
                case 0:
                    a.setValueYear(balance);
                    break;
                case 1:
                    a.setValueJanuary(balance);
                    break;
                case 2:
                    a.setValueFebruary(balance);
                    break;
                case 3:
                    a.setValueMarch(balance);
                    break;
                case 4:
                    a.setValueApril(balance);
                    break;
                case 5:
                    a.setValueMay(balance);
                    break;
                case 6:
                    a.setValueJune(balance);
                    break;
                case 7:
                    a.setValueJuly(balance);
                    break;
                case 8:
                    a.setValueAugust(balance);
                    break;
                case 9:
                    a.setValueSeptember(balance);
                    break;
                case 10:
                    a.setValueOctober(balance);
                    break;
                case 11:
                    a.setValueNovember(balance);
                    break;
                case 12:
                    a.setValueDecember(balance);
                    break;
            }
        }
    }

    @Override
    public Map<String, Double> trialBalance() {
        Map<String, Double> data = new HashMap();
        ErpAccount account = accountService.getLastErpAccount();
        UserInfo userInfo = UserThreadLocal.get();
        Double beginDebitAmount = baseMapper.getBeginDebitAmount(account.getId(), userInfo.getCompanyId(), 1); //借
        Double beginCreditAmount = baseMapper.getBeginDebitAmount(account.getId(), userInfo.getCompanyId(), 2); //贷
        data.put("beginDebitAmount", beginDebitAmount != null ? beginDebitAmount : 0);
        data.put("beginCreditAmount", beginCreditAmount != null ? beginCreditAmount : 0);
        return data;
    }

    /**
     * 获取财务启用期间
     *
     * @author 小啊刚
     * @date 2022-05-16
     */
    public Integer getAccountPeriod(Integer year, Integer companyId) {
        return baseMapper.getAccountPeriod(year, companyId);
    }

}
